#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File    :   OBU_Dismount_Verification_test.py
@Time    :   2025/04/28 13:31:28
@Author  :   YangLiang 
@Version :   1.0
@Contact :   yangl@genvict.com
@License :   (C)Copyright 2022-2025
@Desc    :   OBU防拆认证测试
'''

from pytest_assume.plugin import assume
import pytest
import logging
import time
from commDriver.TS_CAN import *
import allure
import sys
from commDriver.ZEEKR_issuance import ZEEKR_Issuer
import random
sys.dont_write_bytecode = True


class Test_OBU_Dismount_Verification:
    '''
    OBU防拆测试
    '''

    def _verify_random_data(self, Driver, iStep, count=3, length=8):
        """验证随机数数据公共方法
        Args:
            Driver, iStep, count:随机数帧数,   length:长度
        Returns:
            iStep, data: 随机数数据
        """
        iStep, messageCount, data = Driver['CAN'].GetMessageCount(iStep, 0x311, 2)
        with allure.step(f'第{iStep}步:判断是否OBU随机数帧0x311 count={count} # 帧数={count}'):
            with assume: assert messageCount == count, logging.error(f"OBU随机数帧0x311应该={count},实际帧数={messageCount}")
            iStep += 1
        with allure.step(f'第{iStep}步:判断随机数长度 # 数据长度={length}'):
            with assume: assert len(data) == length, logging.error(f"OBU随机数长度应该={length},实际长度={len(data)}")
            iStep += 1
        return iStep, data

    def _verify_dismount_status(self, Driver, iStep, expected_status=0x0):
        """验证防拆认证状态公共方法
        Args:
            Driver
            iStep
            expected_status: 0x00=Success 0x01=Fail.
        Returns:
            iStep
        """
        iStep, OBUDismountSt = Driver['CAN'].getOBUDismountSt(iStep)
        status_desc = "成功" if expected_status == 0x0 else "失败"
        with allure.step(f'第{iStep}步:判断防拆认证状态 # 防拆认证状态应为{status_desc}(0x{expected_status:02X})'):
            with assume: assert OBUDismountSt == expected_status, logging.error(
                f"防拆状态应该=0x{expected_status:02X},实际状态=0x{OBUDismountSt:02X}")
            iStep += 1
        return iStep

    @allure.title('OBU防拆认证校验流程测试')
    @allure.description('OBU防拆认证校验流程测试')
    @pytest.mark.repeat(1)
    def test_OBU_Dismount_Verification_OK(self, action, DismountFail, Driver):
        iStep = 1
        # 1. 发送认证请求
        iStep = Driver['CAN'].send_ETCActiveCmd(iStep)
        # 2. 获取OBU随机数，并验证帧数与数据长度
        iStep, random_data = self._verify_random_data(Driver, iStep)
        # 3. 发送防拆认证UxCDismountData
        iStep = Driver['CAN'].send_UXCDismountData(iStep, random_data)
        time.sleep(0.5)
        # 4. 检查防拆认证状态
        iStep = self._verify_dismount_status(Driver, iStep)
        # 5. 重启OBU
        iStep = Driver['CAN'].restartOBU_Power(Driver, iStep)
        # 6. 检查防拆认证状态
        iStep = self._verify_dismount_status(Driver, iStep)

    @allure.title('同一上电周期内重复OBU防拆认证校验流程测试')
    @allure.description('同一上电周期内重复OBU防拆认证校验流程测试')
    @pytest.mark.repeat(1)
    def test_OBU_Dismount_Verification_OK_Repeat(self, action, DismountFail, Driver):
        iStep = 1
        # 1. 发送认证请求
        iStep = Driver['CAN'].send_ETCActiveCmd(iStep)
        # 2. 获取OBU随机数，并验证帧数与数据长度
        iStep, random_data = self._verify_random_data(Driver, iStep)
        # 3. 发送UxCDismountData
        iStep = Driver['CAN'].send_UXCDismountData(iStep, random_data)
        time.sleep(1)
        # 4. 检查防拆认证状态
        iStep = self._verify_dismount_status(Driver, iStep)      
        # 6. 再次发起防拆验证请求
        iStep = Driver['CAN'].send_ETCActiveCmd(iStep)
        # 7. 获取OBU随机数，并验证帧数与数据长度
        iStep, random_data = self._verify_random_data(Driver, iStep, count=0, length=0)
        # 8. 重启OBU
        iStep = Driver['CAN'].restartOBU_Power(Driver, iStep)
        # 9. 检查防拆认证状态
        iStep = self._verify_dismount_status(Driver, iStep)

    
    @allure.title('OBU防拆认证校验流程测试,不发送UxCDismountData,防拆认证失败')
    @allure.description('OBU防拆认证校验流程测试,不发送UxCDismountData,防拆认证失败')
    def test_OBU_Dismount_Verification_NOK_without_UXCDismountData(self, action, DismountFail, Driver):
        iStep = 1
        # 1. 发送认证请求
        iStep = Driver['CAN'].send_ETCActiveCmd(iStep)
        
        # 2. 获取并存储三次随机数
        random_data_list = []
        for i in range(3): 
            # 获取OBU随机数，并验证帧数与数据长度
            iStep, random_data = self._verify_random_data(Driver, iStep)
            random_data_list.append(random_data)

            if i > 0:  # 从第二次开始比较
                # 3. 比较当前随机数与第一次获取的随机数是否相同
                with allure.step(f'第{iStep}步:比较第{i+1}次与第1次随机数是否相同'):
                    with assume: assert random_data_list[0] == random_data, logging.error(f"第{i+1}次随机数应与第1次相同,实际不相同")
                    iStep += 1
            
            if i < 2:  # 前两次等待5秒
                logging.info("等待5s,查看OBU是否重复发送")
                time.sleep(5)
        # 4. 检查防拆认证状态是否为失败(0x01)
        logging.info("三次后,查看OBU防拆状态是否为失败(0x01)")
        iStep = self._verify_dismount_status(Driver, iStep, expected_status=0x01)
        # 5. 重启OBU
        iStep = Driver['CAN'].restartOBU_Power(Driver, iStep)
        # 6. 检查防拆认证状态
        iStep = self._verify_dismount_status(Driver, iStep, expected_status=0x01)

    @allure.title('OBU防拆认证校验流程测试,发送三次错误的UxCDismountData,防拆认证失败')
    @allure.description('OBU防拆认证校验流程测试,发送三次错误的UxCDismountData,防拆认证失败')
    def test_OBU_Dismount_Verification_NOK_witThreWrong_UXCDismountData(self, action, DismountFail, Driver):
        iStep = 1
        # 1. 发送认证请求
        iStep = Driver['CAN'].send_ETCActiveCmd(iStep)
        # 2. 获取OBU随机数，并验证帧数与数据长度
        iStep, random_data = self._verify_random_data(Driver, iStep)
        # 3. 发送错误的UxCDismountData
        logging.info("发送三次错误的UxCDismountData")
        for i in range(3):
            iStep = Driver['CAN'].send_UXCDismountData(iStep, [0x00] * 8)
            time.sleep(1)
            
        # 4. 三次后，检查防拆认证状态
        iStep = self._verify_dismount_status(Driver, iStep, expected_status=0x01)
        # 5. 重启OBU
        iStep = Driver['CAN'].restartOBU_Power(Driver, iStep)
        # 6. 检查防拆认证状态
        iStep = self._verify_dismount_status(Driver, iStep, expected_status=0x01)

    @allure.title('OBU防拆认证校验流程测试,发送一次错误的UxCDismountData,再发送正确的,防拆认证成功')
    @allure.description('OBU防拆认证校验流程测试,发送一次错误的UxCDismountData,再发送正确的，防拆认证成功')
    def test_OBU_Dismount_Verification_OK_withWrongAndTrue_UXCDismountData(self, action, DismountFail, Driver):
        iStep = 1
        # 1. 发送认证请求
        iStep = Driver['CAN'].send_ETCActiveCmd(iStep)
        # 2. 获取OBU随机数，并验证帧数与数据长度
        iStep, random_data = self._verify_random_data(Driver, iStep)
        # 3. 发送错误的UxCDismountData
        logging.info("发送错误的UxCDismountData")
        iStep = Driver['CAN'].send_UXCDismountData(iStep, [0x00] * 8)
        time.sleep(1)
        # 4. 检查防拆认证状态
        iStep = self._verify_dismount_status(Driver, iStep, expected_status=0x01)
        # 5. 发送正确的UxCDismountData
        iStep = Driver['CAN'].send_UXCDismountData(iStep, random_data)
        time.sleep(1)       
        # 6. 检查防拆认证状态
        iStep = self._verify_dismount_status(Driver, iStep, expected_status=0x00)
        # 7. 重启OBU
        iStep = Driver['CAN'].restartOBU_Power(Driver, iStep)
        # 8. 检查防拆认证状态
        iStep = self._verify_dismount_status(Driver, iStep, expected_status=0x00)

    @allure.title('OBU防拆认证校验流程测试,发送两次错误的UxCDismountData,再发送正确的,防拆认证成功')
    @allure.description('OBU防拆认证校验流程测试,发送两次错误的UxCDismountData,再发送正确的，防拆认证成功')
    def test_OBU_Dismount_Verification_OK_withTwoWrongAndTrue_UXCDismountData(self, action, DismountFail, Driver):
        iStep = 1
        # 1. 发送认证请求
        iStep = Driver['CAN'].send_ETCActiveCmd(iStep)
        # 2. 获取OBU随机数，并验证帧数与数据长度
        iStep, random_data = self._verify_random_data(Driver, iStep)
        # 3. 发送错误的UxCDismountData
        logging.info("发送两次错误的UxCDismountData")
        for i in range(2):
            iStep = Driver['CAN'].send_UXCDismountData(iStep, [0x00] * 8)
            time.sleep(1)
        # 4. 检查防拆认证状态
        iStep = self._verify_dismount_status(Driver, iStep, expected_status=0x01)
        # 5. 发送正确的UxCDismountData
        iStep = Driver['CAN'].send_UXCDismountData(iStep, random_data)
        time.sleep(1)       
        # 6. 检查防拆认证状态
        iStep = self._verify_dismount_status(Driver, iStep, expected_status=0x00)
        # 7. 重启OBU
        iStep = Driver['CAN'].restartOBU_Power(Driver, iStep)
        # 8. 检查防拆认证状态
        iStep = self._verify_dismount_status(Driver, iStep, expected_status=0x00)

    @allure.title('OBU防拆认证校验流程测试,发送三次错误的UxCDismountData,再发送正确的,防拆认证失败')
    @allure.description('OBU防拆认证校验流程测试,发送三次错误的UxCDismountData,再发送正确的，防拆认证失败')
    def test_OBU_Dismount_Verification_OK_withThreeeWrongAndTrue_UXCDismountData(self, action, DismountFail, Driver):
        iStep = 1
        # 1. 发送认证请求
        iStep = Driver['CAN'].send_ETCActiveCmd(iStep)
        # 2. 获取OBU随机数，并验证帧数与数据长度
        iStep, random_data = self._verify_random_data(Driver, iStep)
        # 3. 发送错误的UxCDismountData
        logging.info("发送三次错误的UxCDismountData")
        for i in range(3):
            iStep = Driver['CAN'].send_UXCDismountData(iStep, [0x00] * 8)
            time.sleep(1)
        # 4. 检查防拆认证状态
        iStep = self._verify_dismount_status(Driver, iStep, expected_status=0x01)
        # 5. 发送正确的UxCDismountData
        iStep = Driver['CAN'].send_UXCDismountData(iStep, random_data)
        time.sleep(1)       
        # 6. 检查防拆认证状态
        iStep = self._verify_dismount_status(Driver, iStep, expected_status=0x01)
        # 7. 重启OBU
        iStep = Driver['CAN'].restartOBU_Power(Driver, iStep)
        # 8. 检查防拆认证状态
        iStep = self._verify_dismount_status(Driver, iStep, expected_status=0x01)
    
    @allure.title('上电5分钟后OBU发起防拆认证校验流程测试')
    @allure.description('上电5分钟后OBU发起防拆认证校验流程测试')
    @pytest.mark.repeat(1)
    def test_OBU_Initiate_Dismount_Verification(self, action, DismountFail, Driver):
        iStep = 1
        
        # 1. 等待5分钟
        Driver['CAN'].ClearBuffer()
        logging.info("等待5分钟后OBU发起防拆认证校验流程测试")
        time.sleep(296)
        # 2. 获取OBU随机数，并验证帧数与数据长度
        iStep, random_data = self._verify_random_data(Driver, iStep)
        # 3. 发送UxCDismountData
        iStep = Driver['CAN'].send_UXCDismountData(iStep, random_data)
        time.sleep(1)
        # 4. 检查防拆认证状态
        iStep = self._verify_dismount_status(Driver, iStep)      
        # 5. 重启OBU
        iStep = Driver['CAN'].restartOBU_Power(Driver, iStep)
        # 6. 检查防拆认证状态
        iStep = self._verify_dismount_status(Driver, iStep)

    @allure.title('OBU防拆认证成功,重启到失效验证')
    @allure.description('OBU防拆认证成功,重启到失效验证')
    def test_OBU_Dismount_Verification_OKtoNOK(self, action, Driver):
        iStep = 1
        # 1. 发送认证请求
        iStep = Driver['CAN'].send_ETCActiveCmd(iStep)
        # 2. 获取OBU随机数，并验证帧数与数据长度
        iStep, random_data = self._verify_random_data(Driver, iStep)
        # 3. 发送UxCDismountData
        iStep = Driver['CAN'].send_UXCDismountData(iStep, random_data)
        time.sleep(0.5)
        # 4. 检查防拆认证状态
        iStep = self._verify_dismount_status(Driver, iStep)
        # 5. 重启OBU
        iStep = Driver['CAN'].restartOBU_Power(Driver, iStep)
        # 6. 检查防拆认证状态
        iStep = self._verify_dismount_status(Driver, iStep)
        # 7. 发送认证请求
        iStep = Driver['CAN'].send_ETCActiveCmd(iStep)
        # 8. 获取OBU随机数，并验证帧数与数据长度
        iStep, random_data = self._verify_random_data(Driver, iStep)
        # 9. 发送错误的UxCDismountData
        logging.info("发送三次错误的UxCDismountData")
        for i in range(3):
            iStep = Driver['CAN'].send_UXCDismountData(iStep, [0x00] * 8)
            time.sleep(1)
            
        # 10. 三次后，检查防拆认证状态
        iStep = self._verify_dismount_status(Driver, iStep, expected_status=0x01)
        # 11. 重启OBU
        iStep = Driver['CAN'].restartOBU_Power(Driver, iStep)
        # 12. 检查防拆认证状态
        iStep = self._verify_dismount_status(Driver, iStep, expected_status=0x01)